package com.sixmac.core.aop;

import com.sixmac.core.annotation.Validator;
import com.sixmac.core.base.model.Format;
import com.sixmac.core.toolbox.ajax.AjaxResult;
import com.sixmac.core.toolbox.kit.HttpKit;
import com.sixmac.core.toolbox.kit.StrKit;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 说明：参数验证
 * Created by tangxh on 2016/11/24.
 */
@Aspect
@Component
public class ValidatorAop {

    @Pointcut(value = "@annotation(com.sixmac.core.annotation.Validator)")
    private void cutBefore() {

    }

    @Around("cutBefore()")
    public Object doValidator(ProceedingJoinPoint point) throws Throwable {
        HttpServletRequest request = HttpKit.getRequest();
        MethodSignature ms = (MethodSignature) point.getSignature();
        Method method = ms.getMethod();
        Map<String, String[]> map = request.getParameterMap();
        Validator validator = method.getAnnotation(Validator.class);
        if (validator != null) {
            String[] formats = validator.format();
            String[] names = validator.name();
            AjaxResult res = checkParamMain(names, formats, map);
            if (!res.beSuccess())
                return res;
        }
        return point.proceed();
    }

    /**
     * 验证参数主方法
     *
     * @param formats
     * @param params
     * @throws Exception
     */
    private AjaxResult checkParamMain(String[] names, String[] formats, Map<String, String[]> params) throws Exception {
        AjaxResult res = new AjaxResult();
        if (names.length == formats.length) {
            for (int i = 0; i < formats.length; i++) {
                String format = formats[i];
                String name = names[i];
                String value = params.get(name) == null ? null : params.get(name)[0];
                if (name.equals("phone")) {
                    name = "手机号码";
                } else if (name.equals("password")) {
                    name = "密码";
                }
                if (StrKit.isEmpty(value)) {
                    res.addError(name + " 不能为空");
                    break;
                }

                if (format.contains("len")) {
                    // 检查参数长度是否对应
                    if (!checkLength(format, value, name, res))
                        break;
                } else if (!format.equals(Format.NOT_NULL)) {
                    // 根据正则检查参数是否正确
                    if (!checkReg(format, value, name, res))
                        break;
                }
            }
        } else {
            throw new Exception("验证的参数与格式的长度不一致");
        }
        return res;
    }


    /**
     * 根据长度检查参数是否正确
     *
     * @param format
     * @param value
     * @return
     * @throws Exception
     */
    private boolean checkLength(String name, String format, String value, AjaxResult res) throws Exception {
        String[] nums = format.split("_");
        boolean lenFlag = true;
        if (nums.length == 3) {
            if (nums[1].equals("min")) {
                if (value.length() > Integer.valueOf(nums[2])) {
                    lenFlag = false;
                }
            } else if (nums[2].equals("max")) {
                if (value.length() < Integer.valueOf(nums[1])) {
                    lenFlag = false;
                }
            } else {
                if (value.length() > Integer.valueOf(nums[2]) || value.length() < Integer.valueOf(nums[1])) {
                    lenFlag = false;
                }
            }
        } else if (nums.length == 2) {
            if (value.length() != Integer.valueOf(nums[1])) {
                lenFlag = false;
            }
        } else {
            throw new Exception("长度验证的参数格式不正确");
        }

        if (!lenFlag) {
            res.addError(name + "-length not correct");
            return false;
        }
        return true;
    }

    /**
     * 根据正则检查参数是否正确
     *
     * @param format
     * @param value
     * @param name
     * @return
     */
    private boolean checkReg(String format, String value, String name, AjaxResult res) {
        Pattern pattern = Pattern.compile(format, Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(value);
        if (!matcher.matches()) {
            res.addError(name + "-格式错误");
            return false;
        }
        return true;
    }
}
